package com.matt.service.courseV2.impl;

import com.alibaba.fastjson.JSON;
import com.dotflat.xj.domain.Data;
import com.dotflat.xj.repository.DataRepository;
import com.matt.commons.exception.BusinessException;
import com.matt.domain.Classes;
import com.matt.domain.courseV2.*;
import com.matt.commons.page.PagerQuery;
import com.matt.domain.nursery.NurseryScheduleRecord;
import com.matt.foundation.utils.CopyUtils;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.ExcelOperateUtil;
import com.matt.repository.ClassesRepository;
import com.matt.repository.base.BaseNativeSqlRepository;
import com.matt.repository.courseV2.*;
import com.matt.repository.nursery.NurseryScheduleRecordRepository;
import com.matt.service.NurseryScheduleService;
import com.matt.service.courseV2.AbilityService;
import com.matt.service.courseV2.VendorCourseService;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.io.InputStream;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.commons.model.ErrorCode.JSON_STR_ERROR;
import static com.matt.commons.model.ErrorCode.UNDEFINED;

@Service
public class VendorCourseServiceImpl implements VendorCourseService {

    @Autowired
    private VendorCourseRepository vendorCourseRepository;

    @Autowired
    private VendorCourseRelRepository vendorCourseRelRepository;

    @Autowired
    private DataRepository dataRepository;

    @Autowired
    private BaseNativeSqlRepository baseNativeSqlRepository;

    @Autowired
    private AbilityService abilityService;

    @Autowired
    private  CourseToolRepository courseToolRepository;

    @Autowired
    private NurseryScheduleRecordRepository nurseryScheduleRecordRepository;

    @Autowired
    private ClassesRepository classesRepository;

    @Autowired
    private VendorCourseContentRepository vendorCourseContentRepository;

    @Autowired
    private VendorCoursePackageRepository vendorCoursePackageRepository;

    @Autowired
    private VendorTimeContentRepository vendorTimeContentRepository;

    @Autowired
    private CourseAppendixRepository courseAppendixRepository;

    //分类
    private static  final String  KC_SORT = "kc_sort";
    //年龄
    private static  final String  KC_AGE = "kc_age";
    @Override
    public VendorCourse getVendorCourse(String courseId) {
        return vendorCourseRepository.getOne(courseId);
    }

    @Override
    public VendorCourse addVendorCourse(String title, String author, String content, String attachments, String tools, String persistentTemplateId, int indexInPackage, String tags, String dimensions, String guideVideo) {
        VendorCourse vendorCourse = new VendorCourse();
        vendorCourse.setTitle(title);
        vendorCourse.setAuthor(author);
        vendorCourse.setComment(content);
        vendorCourse.setAttachments(attachments);
        vendorCourse.setTools(tools);
        vendorCourse.setContentTemplateId(persistentTemplateId);
        vendorCourse.setIndexInPackage(indexInPackage);
        vendorCourse.setTags(tags);
        vendorCourse.setDimensions(dimensions);
        vendorCourse.setGuideVideo(guideVideo);
        vendorCourseRepository.save(vendorCourse);
        return vendorCourse;
    }

    @Override
    public Page<VendorCourse> getVendorList(String name, PagerQuery pagerQuery) {
        Specification<VendorCourse> specification = new Specification<VendorCourse>() {
            @Override
            public Predicate toPredicate(Root<VendorCourse> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.isNotBlank(name))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("title"), name)));
                    query.where(predicates.toArray(new Predicate[predicates.size()]));
                    query.orderBy(criteriaBuilder.desc(root.get("created")));
                    return query.getRestriction();
            }
        };
        Page<VendorCourse> liveRecordPage = vendorCourseRepository.findAll(specification, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()));
        return liveRecordPage;
    }


    @Override
    public Page<VendorCourse> packageIdByCourseList(String packageId, PagerQuery pagerQuery) {
        Specification<VendorCourse> specification = new Specification<VendorCourse>() {
            @Override
            public Predicate toPredicate(Root<VendorCourse> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.isNotBlank(packageId))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("course_package_id"), packageId)));
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("created")));
                return query.getRestriction();
            }
        };
        Page<VendorCourse> liveRecordPage = vendorCourseRepository.findAll(specification, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()));
        return liveRecordPage;
    }


    @Override
    public Page<VendorCourse> packageIdInCourseList(List<String> packageIds, PagerQuery pagerQuery) {
        Specification<VendorCourse> specification = new Specification<VendorCourse>() {
            @Override
            public Predicate toPredicate(Root<VendorCourse> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                CriteriaBuilder.In<Object> p4 = criteriaBuilder.in(root.get("coursePackageId"));
                for (String id : packageIds){
                    p4.value(id);
                }

                Predicate p3 = criteriaBuilder.equal(root.get("deleted"), 0);
                Predicate p1 = criteriaBuilder.and( p3, p4);
                query.where(p1);
                query.orderBy(criteriaBuilder.asc(root.get("indexInPackage")));
                return query.getRestriction();
            }
        };
        Page<VendorCourse> liveRecordPage = vendorCourseRepository.findAll(specification, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()));
        return liveRecordPage;
    }


    @Override
    public Page<VendorCourse> courseListV2(String title,String age,String week,String face,Integer type, PagerQuery pagerQuery) {
        Specification<VendorCourse> specification = new Specification<VendorCourse>() {
            @Override
            public Predicate toPredicate(Root<VendorCourse> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {

                List<Predicate> predicates = new ArrayList<>();
                if (Objects.nonNull(type) ) {
                    predicates.add(criteriaBuilder.equal(root.get("type"), type));
                }
                if (Objects.nonNull(age) && !StringUtils.equals("",age)) {
                    String[] ages = age.split("-");
                    if (ages.length>1){
                        Integer ageLow = Integer.valueOf(ages[0]);
                        Integer ageHigh = Integer.valueOf(ages[1]);
                        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("ageLow"), ageLow));
                        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("ageHigh"), ageHigh));
                        predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("ageLow"), ageHigh));
                    }else {
                        predicates.add(criteriaBuilder.lessThanOrEqualTo(root.get("ageLow"), Integer.valueOf(age)));
                        predicates.add(criteriaBuilder.greaterThanOrEqualTo(root.get("ageHigh"), Integer.valueOf(age)));
                    }
                }
                if (Objects.nonNull(title)&& !StringUtils.equals("",title)) {
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("title"),"%" + title + "%")));
                }
                if (Objects.nonNull(week)&& !StringUtils.equals("",week)) {
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("details"),"%" + week+"\"" + "%")));
                }

                if (Objects.nonNull(face)&& !StringUtils.equals("",face)) {
                    predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("details"),"%" + face +"\""+ "%")));
                }

                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("deleted"), 0)));
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.asc(root.get("indexInPackage")));
                return query.getRestriction();
            }
        };
        Page<VendorCourse> liveRecordPage = vendorCourseRepository.findAll(specification, PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize()));
        return liveRecordPage;
    }

    @Override
    public Map list(String packageId, String title, String sort, String age, PagerQuery pagerQuery) {
        List<Data> sortList = dataRepository.findAllByType(KC_SORT);
        List<Data> ageList =dataRepository.findAllByType(KC_AGE);

        String sql = String.format("SELECT vc.id,vc.title,vc.cover,vc.tags,vc.index_in_package indexInPackage  FROM tc_vendor_course vc  LEFT JOIN  xj_data d  ON d.id = vc.sort  LEFT JOIN  xj_data d1 ON d1.id = vc.age " +
                " WHERE vc.course_package_id = '%s' ",packageId);

        if (Objects.nonNull(title)) {
            sql += " and vc.title  LIKE  concat('%', '"+title+"', '%')";
        }
        if (Objects.nonNull(sort)) {
            sql += String.format(" and d.id  ='%s' ", sort);
        }

        if (Objects.nonNull(age)) {
            sql += String.format(" and d1.id  ='%s' ", age);
        }
        List<Object[]> objects = baseNativeSqlRepository.sqlArrayList(sql);

        sql += String.format(" LIMIT  %s , %s", pagerQuery.getPageNum() * pagerQuery.getPageSize(),pagerQuery.getPageSize());
        List<Object[]> objects1 = baseNativeSqlRepository.sqlArrayList(sql);
        List<Map> mapList = new ArrayList<>();
        for (int i = 0; i < objects1.size(); i++) {
            Map map = new HashMap();
            map.put("id", objects1.get(i)[0].toString());
            map.put("title", objects1.get(i)[1].toString());
            map.put("cover", objects1.get(i)[2].toString());
            map.put("tags", objects1.get(i)[3].toString());
            map.put("indexInPackage", Integer.valueOf(objects1.get(i)[4].toString()));
            mapList.add(map);
        }
        Map map = new HashMap();
        map.put("total",objects.size());
        map.put("sortList",sortList);
        map.put("ageList",ageList);
        map.put("list",mapList);
        return map;
    }

    @Override
    @Transactional
    public void addAll(List<VendorCourseRel> vendorCourseRelList) {
        //添加关联关系
        vendorCourseRelRepository.saveAll(vendorCourseRelList);
    }



    @Override
    @Transactional
    public void importTemplate(MultipartFile file) throws Exception{
        InputStream input = file.getInputStream();
        String fileName = file.getOriginalFilename();
        Workbook book = ExcelOperateUtil.getWorkbook(input,fileName);
        Sheet sheet = book.getSheetAt(0);
        List<VendorCoursePackage> vendorCoursePackageList = new ArrayList<>();
        List<VendorCourseRel> vendorCourseRelList  = new ArrayList<>();
        String label = "";
        String coursePackageId = "";
        for (int i = 0 ; i < sheet.getLastRowNum(); i++) {
            Row row1 = sheet.getRow(i+1);

            List<Map> mapList = new ArrayList<>();
            //类型
            Cell cell1 = row1.getCell(0);
            String cellValue1 = "";
            if (Objects.nonNull(cell1)){
                cell1.setCellType(CellType.STRING);
                cellValue1 = cell1.getStringCellValue();
                if (!org.apache.commons.lang3.StringUtils.equals("",cellValue1)){
                    label =  cellValue1;
                }
            }
            //月龄
            Cell cell2 = row1.getCell(1);
            String cellValue2 = "";
            if (Objects.nonNull(cell2)){
                cell2.setCellType(CellType.STRING);
                cellValue2 = cell2.getStringCellValue();

            }
            //周
            Cell cell3 = row1.getCell(2);
            String cellValue3 = "";
            if (Objects.nonNull(cell3)){
                cell3.setCellType(CellType.STRING);
                cellValue3 = cell3.getStringCellValue();
                Map map = new HashMap();
                map.put("title","周");
                map.put("content",cellValue3);
                map.put("type","richtext");
                mapList.add(map);
            }
            //预计时间
            Cell cell4 = row1.getCell(3);
            String cellValue4 = "";
            if (Objects.nonNull(cell4)){
                cell4.setCellType(CellType.STRING);
                cellValue4 = cell4.getStringCellValue();
                Map map = new HashMap();
                map.put("title","预计时间");
                map.put("content",cellValue4);
                map.put("type","richtext");
                mapList.add(map);
            }
            //标题/活动名
            Cell cell5 = row1.getCell(4);
            String cellValue5 = "";
            if (Objects.nonNull(cell5)){
                cell5.setCellType(CellType.STRING);
                cellValue5 = cell5.getStringCellValue();
            }
            //课程能力指标
            Cell cell6 = row1.getCell(5);
            String cellValue6 = "";
            String abilityIds = "";
            if (Objects.nonNull(cell6)){
                cell6.setCellType(CellType.STRING);
                cellValue6 = cell6.getStringCellValue();
                cellValue6 = cellValue6.replace("\uF06C","");
                Map map = new HashMap();
                map.put("title","课程能力指标");
                map.put("content",cellValue6);
                map.put("type","richtext");
                mapList.add(map);
                //能力指标集合
                List<Ability> abilityList = new ArrayList<>();
                String[] cellValue_6 = cellValue6.split("\n");
                for (int j = 0; j < cellValue_6.length; j++) {
                    //能力指标
                    Ability ability = new Ability();
                    ability.setStartTime(Integer.parseInt(cellValue2) * 30  -30 );
                    ability.setEndTime(Integer.parseInt(cellValue2) * 30);
                    ability.setItem("0");
                    ability.setLabel(label);
                    ability.setName(cellValue_6[j]);
                    abilityList.add(ability);
                }
                abilityService.addAll(abilityList);
                List<String> ids = abilityList.stream().map(k->k.getId()).collect(Collectors.toList());
                abilityIds = String.join(",", ids );
            }
            //内容
            Cell cell7 = row1.getCell(6);
            String cellValue7 = "";
            if (Objects.nonNull(cell7)){
                cell7.setCellType(CellType.STRING);
                cellValue7 = cell7.getStringCellValue();
                Map map = new HashMap();
                map.put("title","课程内容");
                map.put("content",cellValue7);
                map.put("type","richtext");
                mapList.add(map);
            }
            //※注意事项
            Cell cell8 = row1.getCell(7);
            String cellValue8 = "";
            if (Objects.nonNull(cell8)){
                cell8.setCellType(CellType.STRING);
                cellValue8 = cell8.getStringCellValue();
                Map map = new HashMap();
                map.put("title","注意事项");
                map.put("content",cellValue8);
                map.put("type","richtext");
                mapList.add(map);
            }

            List<Map> mapList1 = new ArrayList<>();
            //教具
            Cell cell9 = row1.getCell(8);
            String cellValue9 = "";
            String[] cellValue_9  = new String[0];
            if (Objects.nonNull(cell9)){
                cell9.setCellType(CellType.STRING);
                cellValue9 = cell9.getStringCellValue();
                cellValue_9 = cellValue9.split("\n");
            }
            //教具 - 媒体/附件
            Cell cell10 = row1.getCell(9);
            String cellValue10 = "";
            String[] cellValue_10  = new String[0];
            if (Objects.nonNull(cell10)){
                cell10.setCellType(CellType.STRING);
                cellValue10 = cell10.getStringCellValue();
                cellValue_10 = cellValue10.split("\n");
            }

            for (int j = 0; j < cellValue_9.length; j++) {
                Map map = new HashMap();
                map.put("name",cellValue_9[j]);
                map.put("number",1);
                if (j < cellValue_10.length){
                    map.put("imgUrl",cellValue_10[j]);
                }
                map.put("unit","件");
                map.put("userName","所有");
                mapList1.add(map);
            }

            //课程包
            VendorCoursePackage vendorCoursePackage = new VendorCoursePackage();
            if (!org.apache.commons.lang3.StringUtils.equals(cellValue1,"")){
                vendorCoursePackage.setPrice(0);
                vendorCoursePackage.setName(cellValue1);
                vendorCoursePackage.setDimensions(cellValue2);

                VendorCoursePackage vendorCoursePackage2 =  vendorCoursePackageRepository.findByNameAndDimensionsAndPrice(cellValue1,cellValue2,0);
                if (Objects.isNull(vendorCoursePackage2)){
                    //添加课程包
                    VendorCoursePackage  vendorCoursePackage1 = vendorCoursePackageRepository.save(vendorCoursePackage);
                    CopyUtils.copyProperties(vendorCoursePackage1,vendorCoursePackage);
                }else {
                    vendorCoursePackage.setId(vendorCoursePackage2.getId());
                }
                //课程包id
                coursePackageId = vendorCoursePackage.getId();
                vendorCoursePackageList.add(vendorCoursePackage);
            }


            //课程
            VendorCourse vendorCourse = new VendorCourse();
            vendorCourse.setCoursePackageId(coursePackageId);
            vendorCourse.setCover("");
            vendorCourse.setTags("");
            vendorCourse.setTitle(cellValue5);
            String str = JSON.toJSONString(mapList);
            vendorCourse.setContentTemplate(str);
            String str1 = JSON.toJSONString(mapList1);
            vendorCourse.setTools(str1);
            //添加课程,
            vendorCourseRepository.save(vendorCourse);

            //课程关联
            VendorCourseRel vendorCourseRel = new VendorCourseRel();
            if (!org.apache.commons.lang3.StringUtils.equals(abilityIds,"")){
                vendorCourseRel.setAbilityIds(abilityIds);
                vendorCourseRel.setVendorCourseId(vendorCourse.getId());
                vendorCourseRelList.add(vendorCourseRel);
            }

            for (int j = 0; j < cellValue_9.length; j++) {
                CourseTool courseTool = new CourseTool();
                if (j < cellValue_10.length){
                    courseTool.setImgUrl(cellValue_10[j]);
                }

                courseTool.setTitle(cellValue_9[j]);
                courseTool.setUnit("件");
                CourseTool courseTool1 = courseToolRepository.findByTitle(cellValue_9[j]);
                if (Objects.isNull(courseTool1)){
                    courseToolRepository.save(courseTool);
                }
            }

        }
        //批量保存信息
        addAll(vendorCourseRelList);
    }


    @Override
    public String addScheduleRel(String vendorCourseId, String scheduleRecordId) {
        NurseryScheduleRecord nurseryScheduleRecord = nurseryScheduleRecordRepository.getOne(scheduleRecordId);
        if (Objects.isNull(nurseryScheduleRecord)){
            throw new BusinessException(UNDEFINED, "对象不存在");
        }
        if (Objects.isNull( vendorCourseRepository.getOne(vendorCourseId))){
            throw new BusinessException(UNDEFINED, "对象不存在");
        }
        if (1 ==nurseryScheduleRecord.getCategory()){
            nurseryScheduleRecord.setResObj(vendorCourseId);
            nurseryScheduleRecordRepository.save(nurseryScheduleRecord);
            return "添加成功";
        }else {
            throw new BusinessException(UNDEFINED, "课程非主题课");
        }
    }

    @Override
    public Page<VendorCourse> getClassVendor(String classesId, PagerQuery pagerQuery) {
        //通过班级ID获取班级信息
        Classes classes = classesRepository.getOne(classesId);
        if (Objects.isNull(classes)){
            throw new BusinessException(UNDEFINED, "对象不存在");
        }
        Date date = new Date();
        //计算入园月龄
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();

        LocalDate currentDate = localDate.plusMonths(classes.getBeginMonth());
        LocalDate createdDate = LocalDate.parse( DateUtil.convertStr(classes.getCreated()));
        Integer diffMonth = Period.between(createdDate,currentDate).getMonths();
        //计算入园天数
        Integer diffDay = Period.between(createdDate,currentDate).getDays();

        System.out.println("diffMonth" + diffMonth);
        System.out.println("diffDay" + diffDay);

        List<VendorCoursePackage> list = vendorCoursePackageRepository.findByMonth(diffMonth);

        List<String> ids = list.stream().map(k->k.getId()).collect(Collectors.toList());
        String[] coursePackageIds = ids.toArray(new String[ids.size()]);
        PageRequest pageRequest = PageRequest.of(pagerQuery.getPageNum(), pagerQuery.getPageSize());
        Page<VendorCourse>  list1 = vendorCourseRepository.findByCoursePackageIdIn(coursePackageIds,pageRequest);
        return list1;
    }

    @Override
    public List<VendorCourseContent> findByCourseId(String courseId) {
        return vendorCourseContentRepository.findByCourseIdOrderByOrderNumAsc(courseId);
    }

    @Override
    public List<VendorCourseContent> findByCourseId(String courseId, Integer detailsType) {
        return vendorCourseContentRepository.findByCourseIdAndDetailsTypeOrderByOrderNumAsc(courseId,detailsType);
    }

    @Override
    public List<VendorCourseContent> findByVendorPackageId(String vendorPackageId) {
        return vendorCourseContentRepository.findByVendorPackageIdOrderByOrderNumAsc(vendorPackageId);
    }

    @Override
    public List<VendorCourseContent> findVendorPackageId(String  courseId) {
        return vendorCourseContentRepository.findVendorPackageIdOrderByOrderNumAsc( courseId);
    }

    @Override
    public List<VendorTimeContent> findByVendorPackageIdTimeContent(String vendorPackageId) {
        return vendorTimeContentRepository.findByVendorPackageId(vendorPackageId);
    }

    @Override
    public List<CourseAppendix> courseAppendix() {
        return courseAppendixRepository.findAll();
    }
}
